<template>
  <div class="voice-chat">
    <el-row :gutter="20">
      <el-col :span="16">
        <el-card class="main-card">
          <div slot="header">
            <h2>智能查询助手</h2>
          </div>
          <div class="chat-content">
            <div class="conversation-area" ref="conversationArea">
              <div v-if="messages.length === 0" class="welcome-message">
                <h3>欢迎使用智能查询助手</h3>
                <p>您可以问我关于企业运营的问题，例如：</p>
                <ul>
                  <li>"一分公司前年的5月份的维保情况"</li>
                  <li>"今年一季度火警发生次数"</li>
                  <li>"二分公司设备故障率情况"</li>
                </ul>
              </div>
              
              <div 
                v-for="(message, index) in messages" 
                :key="index" 
                class="message-item"
                :class="{ 'user-message': message.type === 'user', 'system-message': message.type === 'system' }"
              >
                <div class="message-info">
                  <strong>{{ message.type === 'user' ? '您：' : '系统：' }}</strong>
                  <small>{{ formatTime(message.timestamp) }}</small>
                </div>
                <div class="message-content">{{ message.content }}</div>
              </div>
              
              <div v-if="isProcessing" class="message-item system-message">
                <div class="message-info">
                  <strong>系统：</strong>
                </div>
                <div class="message-content processing">
                  <span>处理中</span>
                  <span class="dot">.</span>
                  <span class="dot">.</span>
                  <span class="dot">.</span>
                </div>
              </div>
            </div>
            
            <div class="input-area">
              <el-input
                v-model="query"
                placeholder="请输入您的问题，例如：一分公司前年的5月份的维保情况"
                type="textarea"
                :rows="3"
                :disabled="isProcessing"
                @keyup.ctrl.enter.native="handleSendQuery"
              ></el-input>
              <div class="action-buttons">
                <el-button 
                  type="primary" 
                  @click="handleSendQuery" 
                  :loading="isProcessing"
                  :disabled="!query.trim()"
                >发送</el-button>
                <el-button @click="handleClear">清空对话</el-button>
              </div>
            </div>
          </div>
        </el-card>
      </el-col>
      
      <el-col :span="8">
        <el-card class="status-card">
          <div slot="header">
            <h3>连接状态</h3>
          </div>
          <div class="connection-status">
            <p>
              <strong>WebSocket状态：</strong> 
              <el-tag :type="isConnected ? 'success' : 'danger'">
                {{ isConnected ? '已连接' : '未连接' }}
              </el-tag>
            </p>
            <p>
              <strong>连接地址：</strong>
              <span>{{ serverUrl || '未连接' }}</span>
            </p>
            <p v-if="sessionId">
              <strong>会话ID：</strong>
              <span>{{ sessionId }}</span>
            </p>
            <p v-if="lastResponseTime">
              <strong>最后响应：</strong>
              <span>{{ formatTime(lastResponseTime) }}</span>
            </p>
            <div class="action-buttons">
              <el-button 
                type="primary" 
                size="small" 
                @click="connectWebSocket" 
                :disabled="isConnected"
              >连接服务器</el-button>
              <el-button 
                type="danger" 
                size="small" 
                @click="disconnectWebSocket" 
                :disabled="!isConnected"
              >断开连接</el-button>
              <el-button
                type="warning"
                size="small"
                @click="renewSession"
                :disabled="!isConnected"
              >重置会话</el-button>
            </div>
          </div>
          
          <div class="instructions">
            <h4>使用说明：</h4>
            <ol>
              <li>在输入框中输入您的问题</li>
              <li>点击"发送"按钮或按Ctrl+Enter发送</li>
              <li>系统会分析您的问题并提供回答</li>
            </ol>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import axios from 'axios';
import SockJS from 'sockjs-client';
import webstomp from 'webstomp-client';

export default {
  name: 'VoiceChat',
  data() {
    return {
      query: '',
      messages: [],
      isProcessing: false,
      isConnected: false,
      serverUrl: '/ws',
      stompClient: null,
      sessionId: null,
      lastResponseTime: null,
      subscriptions: [],
      lastApiData: null,
      apiResponseTimeout: null,
      hasLLMResponse: false
    };
  },
  methods: {
    async handleSendQuery() {
      if (!this.query.trim() || this.isProcessing) return;
      
      const userQuery = this.query.trim();
      this.query = ''; // 清空输入框
      this.isProcessing = true;
      
      // 添加用户消息
      this.addMessage('user', userQuery);
      
      try {
        if (this.isConnected && this.stompClient) {
          // 使用WebSocket发送
          await this.sendQueryViaWebSocket(userQuery);
        } else {
          // 使用HTTP发送
          await this.sendQueryViaHttp(userQuery);
        }
      } catch (error) {
        console.error('处理查询失败:', error);
        this.addMessage('system', '处理查询时出错，请稍后重试');
      } finally {
        this.isProcessing = false;
        this.scrollToBottom();
      }
    },
    
    async sendQueryViaWebSocket(query) {
      return new Promise((resolve, reject) => {
        try {
          // 重置LLM响应状态
          this.hasLLMResponse = false;
          if (this.apiResponseTimeout) {
            clearTimeout(this.apiResponseTimeout);
            this.apiResponseTimeout = null;
          }
          
          // 确保有会话ID
          if (!this.sessionId) {
            this.sessionId = 'session-' + Math.random().toString(36).substring(2, 15);
          }
          
          console.log(`使用会话ID: ${this.sessionId} 发送查询`);
          
          // 创建消息对象
          const message = {
            sessionId: this.sessionId,
            query: query,
            timestamp: Date.now()
          };
          
          // 发送消息
          this.stompClient.send('/app/query', JSON.stringify(message), {});
          console.log('已通过WebSocket发送查询', message);
          
          // 标记请求已完成（用于处理中间状态消息）
          let requestCompleted = false;
          let processingAcknowledged = false;
          let finalResponseReceived = false;  // 添加标记，表示是否已收到最终响应
          let apiDataReceived = false; // 是否收到API数据
          
          // 创建超时处理 - 两次超时设置
          // 第一次较短超时，仅用于检查是否收到"正在处理"的消息
          const processingTimeout = setTimeout(() => {
            if (!processingAcknowledged && !requestCompleted) {
              console.log('未收到处理确认，可能需要重试');
              // 但不中断，继续等待最终响应
            }
          }, 3000); // 3秒
          
          // 第二次较长超时，用于检查是否收到最终结果
          const finalTimeout = setTimeout(() => {
            if (!requestCompleted) {
              console.log('WebSocket响应超时（30秒），尝试HTTP请求');
              window.removeEventListener('ws_message', messageHandler);
              
              // 如果已经收到API数据，使用它生成响应
              if (apiDataReceived && this.lastApiData) {
                const backupResponse = this.generateBackupResponse(this.lastApiData, query);
                if (backupResponse) {
                  console.log('使用API数据生成备用响应');
                  this.addMessage('system', backupResponse);
                  resolve({ response: backupResponse, fromBackup: true });
                  return;
                }
              }
              
              // 尝试HTTP请求
              this.sendQueryViaHttp(query)
                .then(resolve)
                .catch(reject);
            }
          }, 30000); // 30秒，给后端足够的处理时间
          
          // 设置消息处理器
          const messageHandler = event => {
            try {
              // 从事件中获取消息
              const message = event.detail;
              // 解析消息体
              const response = JSON.parse(message.body);
              console.log('收到WebSocket响应:', response);
              
              // 验证会话ID匹配
              if (response.sessionId && response.sessionId !== this.sessionId) {
                console.log('忽略不匹配的会话ID:', response.sessionId);
                return; // 忽略不属于当前会话的消息
              }
              
              // 检查是否收到API数据
              if (response.company || response.period || response.completion_rate) {
                console.log('收到API数据:', response);
                apiDataReceived = true;
                
                // 存储API数据，以便在发生错误时可以使用
                this.lastApiData = response;
                
                // 如果只有API数据没有其他响应，先不处理，等待LLM响应
                if (!response.response && !response.content && !response.answer) {
                  console.log('收到API数据，等待LLM响应');
                  return;
                }
              }
              
              // 检查是否是中间状态消息
              if (response.message && response.message.includes('正在处理') && !requestCompleted) {
                processingAcknowledged = true;
                console.log('已收到处理确认，等待最终结果');
                // 不完成请求，继续等待最终结果
                return;
              }
              
              // 检查是否有错误
              if (response.error && !finalResponseReceived) {
                console.log('收到错误响应:', response.error);
                
                // 如果有API数据，可以尝试生成一个基于数据的备用响应
                if (apiDataReceived && this.lastApiData) {
                  const backupResponse = this.generateBackupResponse(this.lastApiData, query);
                  if (backupResponse) {
                    finalResponseReceived = true;
                    if (!requestCompleted) {
                      clearTimeout(processingTimeout);
                      clearTimeout(finalTimeout);
                      requestCompleted = true;
                      window.removeEventListener('ws_message', messageHandler);
                      
                      this.lastResponseTime = Date.now();
                      this.addMessage('system', backupResponse);
                      resolve({ response: backupResponse, fromBackup: true });
                      return;
                    }
                  }
                }
                
                // 如果没有备用响应，则显示错误
                finalResponseReceived = true;
                if (!requestCompleted) {
                  clearTimeout(processingTimeout);
                  clearTimeout(finalTimeout);
                  requestCompleted = true;
                  window.removeEventListener('ws_message', messageHandler);
                  
                  this.lastResponseTime = Date.now();
                  const errorMsg = "抱歉，处理您的查询时出现了问题，请稍后再试。";
                  this.addMessage('system', errorMsg);
                  resolve({ response: errorMsg, error: response.error });
                }
                return;
              }
              
              // 如果是最终结果或确定的响应，并且尚未处理过最终响应
              if ((response.response || response.content || response.answer) && !finalResponseReceived) {
                finalResponseReceived = true; // 标记已收到最终响应
                this.hasLLMResponse = true; // 标记已收到LLM响应
                
                // 如果请求尚未完成，则完成它
                if (!requestCompleted) {
                  clearTimeout(processingTimeout);
                  clearTimeout(finalTimeout);
                  requestCompleted = true;
                  window.removeEventListener('ws_message', messageHandler);
                  
                  this.lastResponseTime = Date.now();
                  
                  // 使用适当的响应字段
                  const content = response.response || response.content || response.answer;
                  if (content) {
                    this.addMessage('system', content);
                    resolve(response);
                  } else {
                    // 如果没有找到有效的响应内容
                    console.log('响应中没有内容字段');
                    this.addMessage('system', '收到无效的响应');
                    reject(new Error('无效的响应数据'));
                  }
                } else {
                  console.log('已经处理过最终响应，忽略重复消息');
                }
              }
            } catch (err) {
              console.error('处理WebSocket响应出错:', err);
              // 只有在请求尚未完成时才处理错误
              if (!requestCompleted) {
                clearTimeout(processingTimeout);
                clearTimeout(finalTimeout);
                requestCompleted = true;
                window.removeEventListener('ws_message', messageHandler);
                reject(err);
              }
            }
          };
          
          // 添加事件监听器
          window.addEventListener('ws_message', messageHandler);
          
        } catch (error) {
          console.error('发送WebSocket查询失败:', error);
          this.sendQueryViaHttp(query)
            .then(resolve)
            .catch(reject);
        }
      });
    },
    
    // 根据API数据生成备用响应
    generateBackupResponse(apiData, query) {
      try {
        console.log('生成备用响应，数据:', apiData);
        
        // 如果有关键数据字段，生成响应
        if (apiData && apiData.company && apiData.period) {
          let companyName = '';
          try {
            companyName = decodeURIComponent(apiData.company);
          } catch (e) {
            companyName = apiData.company; // 如果解码失败，使用原始值
          }
          
          const period = apiData.period || '未知时间';
          const status = apiData.status || '良好';
          const completionRate = apiData.completion_rate !== undefined ? apiData.completion_rate : '未知';
          const maintainedDevices = apiData.maintained_devices !== undefined ? apiData.maintained_devices : '未知数量';
          const totalDevices = apiData.total_devices !== undefined ? apiData.total_devices : '未知数量';
          const faultyDevices = apiData.faulty_devices !== undefined ? apiData.faulty_devices : '未知数量';
          
          let response = `根据系统记录，${companyName}在${period}的维保工作情况${status}。\n\n`;
          
          // 添加具体数据
          if (completionRate !== '未知') {
            response += `维保完成率为${completionRate}%。`;
          }
          
          if (maintainedDevices !== '未知数量') {
            response += `\n总计维护了${maintainedDevices}台设备`;
            if (totalDevices !== '未知数量') {
              response += `（总设备${totalDevices}台）`;
            }
            response += '。';
          }
          
          if (faultyDevices !== '未知数量') {
            response += `\n检测到${faultyDevices}台设备存在故障。`;
          }
          
          // 根据状态添加评价
          if (status === '优' || status === '良好') {
            response += '\n\n整体维保工作状况良好，符合预期。';
          } else if (status === '需改进' || status === '一般') {
            response += '\n\n维保工作有待改进，建议加强管理。';
          } else if (status === '差' || status === '不良') {
            response += '\n\n维保工作状况不佳，需要立即改进。';
          }
          
          response += '\n\n以上是系统基于数据分析的结果。如需更详细信息，请稍后再试。';
          
          console.log('生成的备用响应:', response);
          return response;
        }
        
        // 如果数据不完整，返回通用消息
        return null;
      } catch (error) {
        console.error('生成备用响应出错:', error);
        return "根据系统数据，我们已收到您的查询，但无法生成完整响应。请稍后再试。";
      }
    },
    
    async sendQueryViaHttp(query) {
      try {
        // 保存查询，以便在出错时可以重新使用
        const savedQuery = query;
        
        // 直接连接后端API
        const response = await axios.post('/api/langchain/query', { 
          query,
          sessionId: this.sessionId || 'http-session'
        });
        
        // 检查是否收到API数据
        if (response.data && (response.data.company || response.data.period || response.data.completion_rate)) {
          console.log('HTTP响应包含API数据:', response.data);
          this.lastApiData = response.data; // 存储API数据用于可能的备用响应
        }
        
        // 检查是否有错误响应
        if (response.data && response.data.error) {
          console.warn('HTTP请求返回错误:', response.data.error);
          
          // 尝试使用之前缓存的API数据生成备用响应
          if (this.lastApiData) {
            const backupResponse = this.generateBackupResponse(this.lastApiData, savedQuery);
            if (backupResponse) {
              this.addMessage('system', backupResponse);
              return { response: backupResponse, fromBackup: true };
            }
          }
          
          // 返回友好的错误信息
          const errorMsg = "抱歉，处理您的查询时出现了问题，请稍后再试。";
          this.addMessage('system', errorMsg);
          return { error: response.data.error, response: errorMsg };
        }
        
        // 处理正常响应
        if (response.data && (response.data.answer || response.data.content || response.data.response)) {
          const content = response.data.answer || response.data.content || response.data.response;
          this.addMessage('system', content);
          return response.data;
        } else {
          throw new Error('无效的响应数据');
        }
      } catch (error) {
        console.error('HTTP请求失败:', error);
        
        // 尝试使用之前缓存的API数据生成备用响应
        if (this.lastApiData) {
          const backupResponse = this.generateBackupResponse(this.lastApiData, query);
          if (backupResponse) {
            this.addMessage('system', backupResponse);
            return { response: backupResponse, fromBackup: true };
          }
        }
        
        // 如果没有API数据或无法生成备用响应，则显示错误
        const errorMsg = "无法连接到服务器，请稍后重试";
        this.addMessage('system', errorMsg);
        throw error;
      }
    },
    
    addMessage(type, content) {
      this.messages.push({
        type,
        content,
        timestamp: new Date()
      });
      this.scrollToBottom();
    },
    
    scrollToBottom() {
      this.$nextTick(() => {
        if (this.$refs.conversationArea) {
          this.$refs.conversationArea.scrollTop = this.$refs.conversationArea.scrollHeight;
        }
      });
    },
    
    formatTime(timestamp) {
      if (!timestamp) return '';
      const date = new Date(timestamp);
      return `${date.getHours()}:${String(date.getMinutes()).padStart(2, '0')}`;
    },
    
    handleClear() {
      this.messages = [];
    },
    
    connectWebSocket() {
      try {
        this.addMessage('system', '正在连接到服务器...');
        
        // 创建SockJS连接
        const socket = new SockJS('/ws');
        
        // 创建Stomp客户端
        this.stompClient = webstomp.over(socket);
        
        // 禁用调试日志
        this.stompClient.debug = () => {};
        
        // 连接到服务器
        this.stompClient.connect(
          {}, 
          frame => {
            console.log('WebSocket连接成功:', frame);
            this.isConnected = true;
            this.addMessage('system', '已成功连接到服务器');
            
            // 创建会话ID
            if (!this.sessionId) {
              this.sessionId = 'session-' + Math.random().toString(36).substring(2, 15);
            }
            
            // 订阅主要响应主题
            this.subscribeToTopics();
          },
          error => {
            console.error('WebSocket连接失败:', error);
            this.isConnected = false;
            this.addMessage('system', '连接服务器失败，将使用HTTP模式');
          }
        );
      } catch (error) {
        console.error('创建WebSocket连接失败:', error);
        this.isConnected = false;
        this.addMessage('system', '无法连接到服务器，将使用HTTP模式');
      }
    },
    
    subscribeToTopics() {
      if (!this.stompClient || !this.isConnected) return;
      
      try {
        // 订阅通用主题
        const commonSub = this.stompClient.subscribe('/topic/response', message => {
          console.log('收到通用响应:', message);
          this.handleWebSocketMessage(message);
        });
        this.subscriptions.push(commonSub);
        
        // 订阅会话特定主题
        if (this.sessionId) {
          const sessionSub = this.stompClient.subscribe(`/topic/response/${this.sessionId}`, message => {
            console.log(`收到会话 ${this.sessionId} 的响应:`, message);
            this.handleWebSocketMessage(message);
          });
          this.subscriptions.push(sessionSub);
        }
        
        console.log('已订阅所有主题');
      } catch (error) {
        console.error('订阅主题失败:', error);
      }
    },
    
    handleWebSocketMessage(message) {
      try {
        // 解析消息内容
        const data = JSON.parse(message.body);
        console.log('处理WebSocket消息:', data);
        
        // 触发自定义事件，以便消息处理器可以接收
        const event = new CustomEvent('ws_message', { detail: message });
        window.dispatchEvent(event);
        
        // 检查是否是API数据响应
        // 如果是API数据而没有response/content/answer字段，可能是中间结果
        if (data.success === true && data.company && data.period && !data.response && !data.content && !data.answer) {
          console.log('检测到API数据结果，但无LLM响应，生成备用响应');
          const backupResponse = this.generateBackupResponse(data, "");
          if (backupResponse && !this.hasLLMResponse) {
            // 如果正在等待LLM响应，不立即显示备用响应
            // 改为存储API数据，等待更长时间看LLM是否会返回
            this.lastApiData = data;
            
            // 设置超时检查LLM是否响应
            if (!this.apiResponseTimeout) {
              this.apiResponseTimeout = setTimeout(() => {
                if (this.lastApiData && !this.hasLLMResponse) {
                  console.log('LLM未响应，显示API数据的备用响应');
                  const backupMsg = this.generateBackupResponse(this.lastApiData, "");
                  if (backupMsg) {
                    this.addMessage('system', backupMsg);
                    this.hasLLMResponse = true; // 防止重复显示
                  }
                }
                this.apiResponseTimeout = null;
              }, 5000); // 5秒后检查
            }
          }
          return;
        }
        
        // 如果有LLM生成的响应，显示它
        if (data.response || data.content || data.answer) {
          this.hasLLMResponse = true; // 标记已收到LLM响应
          if (this.apiResponseTimeout) {
            clearTimeout(this.apiResponseTimeout);
            this.apiResponseTimeout = null;
          }
          
          const content = data.response || data.content || data.answer;
          this.addMessage('system', content);
        }
      } catch (error) {
        console.error('处理WebSocket消息出错:', error);
      }
    },
    
    disconnectWebSocket() {
      if (this.stompClient) {
        // 取消所有订阅
        this.subscriptions.forEach(sub => {
          try {
            if (sub && sub.unsubscribe) {
              sub.unsubscribe();
            }
          } catch (e) {
            console.error('取消订阅出错:', e);
          }
        });
        this.subscriptions = [];
        
        // 断开连接
        try {
          this.stompClient.disconnect();
        } catch (e) {
          console.error('断开连接出错:', e);
        }
        
        this.stompClient = null;
        this.isConnected = false;
        this.addMessage('system', '已断开与服务器的连接');
      }
    },
    
    renewSession() {
      this.sessionId = 'session-' + Math.random().toString(36).substring(2, 15);
      this.lastResponseTime = null;
      this.addMessage('system', '已重置会话，新会话ID: ' + this.sessionId);
      
      // 重新订阅主题
      if (this.isConnected && this.stompClient) {
        // 先取消所有订阅
        this.subscriptions.forEach(sub => {
          try {
            if (sub && sub.unsubscribe) {
              sub.unsubscribe();
            }
          } catch (e) {
            console.error('取消订阅出错:', e);
          }
        });
        this.subscriptions = [];
        
        // 重新订阅
        this.subscribeToTopics();
      }
    }
  },
  mounted() {
    // 连接WebSocket
    this.connectWebSocket();
    
    // 显示欢迎消息
    this.addMessage('system', '欢迎使用智能查询助手！您可以输入问题，例如："一分公司前年的5月份的维保情况"');
  },
  beforeDestroy() {
    this.disconnectWebSocket();
  }
};
</script>

<style scoped>
.voice-chat {
  max-width: 1200px;
  margin: 0 auto;
}

.main-card, .status-card {
  height: calc(100vh - 20px);
  display: flex;
  flex-direction: column;
}

.chat-content {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.conversation-area {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
  margin-bottom: 20px;
}

.message-item {
  margin-bottom: 15px;
  max-width: 80%;
  padding: 10px 15px;
  border-radius: 10px;
  position: relative;
}

.user-message {
  margin-left: auto;
  background-color: #ecf5ff;
  border: 1px solid #d9ecff;
}

.system-message {
  margin-right: auto;
  background-color: #f0f9eb;
  border: 1px solid #e1f3d8;
}

.message-info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
  font-size: 12px;
}

.message-content {
  word-break: break-word;
}

.welcome-message {
  text-align: center;
  padding: 20px;
  color: #909399;
}

.welcome-message ul {
  text-align: left;
  margin-top: 10px;
  padding-left: 20px;
}

.welcome-message li {
  margin-bottom: 5px;
}

.input-area {
  margin-top: auto;
}

.action-buttons {
  margin-top: 10px;
  display: flex;
  justify-content: flex-end;
}

.connection-status {
  margin-bottom: 20px;
}

.instructions {
  margin-top: 20px;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.processing .dot {
  animation: fadeInOut 1.5s infinite;
  opacity: 0;
}

.processing .dot:nth-child(2) {
  animation-delay: 0.5s;
}

.processing .dot:nth-child(3) {
  animation-delay: 1s;
}

@keyframes fadeInOut {
  0% { opacity: 0; }
  50% { opacity: 1; }
  100% { opacity: 0; }
}
</style>